package com.xiguthings.waka.web.controller.base;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xiguthings.waka.command.CodeConstant;
import com.xiguthings.waka.exception.HttpSendErrorException;

import com.xiguthings.waka.po.extpo.Page;
import com.xiguthings.waka.publicUtils.PropertiesUtil;
import com.xiguthings.waka.service.base.IBaseService;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.xiguthings.waka.exception.BussinessException;
import com.xiguthings.waka.publicUtils.StringUtils;

/**
 */
public abstract class AbstractController {
    protected String filePath;

    protected Logger logger;

    public AbstractController() {
        super();
        logger = LoggerFactory.getLogger(this.getClass());
        this.filePath = PropertiesUtil.getInstance().getPro("config/app.properties", "file.path");
    }

    protected HttpServletRequest getRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }

    // 常量key
    public static final String Key_httpSession_authority = "authority";// 存在session中的权限对象的key
    public static final String Key_loginType_maintainer = "Maintainer";// 登录类型——运维人员登录类型
    public static final String Key_loginType_user = "User";// 登录类型——用户登录类型（小程序）

    /**
     * 在session中的当前user
     */
    public static final String SESSION_CRN_USER = "crn_user";

    public static final String SESSION_CRN_MAINTAINER = "crn_maintainer";
    /**
     * 在session中的当前微信用户详情
     */
    public static final String SESSION_CRUN_SNSAPIENTITY = "crun_snsapiEntity";

    public static final String SNSAPI_USERINFO = "snsapi_userinfo";


    protected HttpSession getSession() {
        return getRequest().getSession();
    }

    protected PropertiesFactoryBean propertiesFactory;

//	/**
//	 * 
//	 * 
//	 * 判断对某个action 方法时候具有权限，在action方法调用之前，验证方法权限，根据结果进行相应处理
//	 * ，action二进制值和注意是资源id不是资源typeId<br/>
//	 * <br/>
//	 * <p>
//	 * Author: leiyu<br/>
//	 * <p>
//	 * Date: 2014-4-2-下午2:12:40<br/>
//	 * <p>
//	 * 
//	 * @param
//	 * @param
//	 * @return
//	 * 
//	 */
//	protected boolean hasPermission(String actionCode) {
//		return true;
//	}
//
//	/**
//	 * 封装ajax返回Map的信息<br/>
//	 * <p>
//	 * Description: 将ajax方法返回的Map信息进行统一的封装，使用时只需调用此方法传入参数即可。<br>
//	 * <p>
//	 * 如果自定义消息customMsgDesc不为空则使用customMsgDesc，否则根据msgDesc去查找相应的异常信息。 <br/>
//	 * <p>
//	 * Author: dencl<br/>
//	 * <p>
//	 * Date: 2014-4-2-下午2:49:13<br/>
//	 * <p>
//	 * 
//	 * @param opResult
//	 *            结果
//	 * @param msgType
//	 *            消息类型
//	 * @param msgDesc
//	 *            消息描述
//	 * @param customMsgDesc
//	 *            自定义消息
//	 * @return
//	 * 
//	 */
//	protected Map<String, String> packageAjaxReturnMap(String opResult, String msgType, String msgDesc,
//			String customMsgDesc) {
//		Map<String, String> map = new HashMap<String, String>(4);
//
//		map.put(ERROR_KEY_OP_RESULT, opResult);
//		map.put(ERROR_KEY_MSG_TYPE, msgType);
//
//		if (StringUtils.isNotBlank(customMsgDesc)) {
//			map.put(ERROR_KEY_MSG_DESC, customMsgDesc);
//		} else {
//			map.put(ERROR_KEY_MSG_DESC, "");
//		}
//
//		return map;
//
//	}

//	protected Map<String, String> ajaxReturnMap(String opStatus, String msgDesc) {
//		Map<String, String> map = new HashMap<String, String>(2);
//		map.put(KEY_OP_STATUS, opStatus);
//		map.put(KEY_MSG_DESC, msgDesc);
//		return map;
//
//	}

    protected ResponseEntity ajaxReturnMap(int code, String msgDesc, Object data) {
        ResponseEntity entity = new ResponseEntity();
        entity.setCode(code);
        entity.setMsg(msgDesc);
        entity.setData(data);
        return entity;
    }

    // protected Map<String, Object> ajaxPageMap(PaginationList<?> plist,
    // List<?> pageData)
    // {
    // final String PAGE_NUMBER = "pageNumber";
    // final String PAGE_SIZE = "pageSize";
    // final String TOTAL_PAGE = "totalPage";
    // final String TOTAL_RECORD = "totalRecord";
    // final String PAGE_DATA = "pageData";
    // Map<String, Object> map = new HashMap<String, Object>();
    // map.put(PAGE_NUMBER, plist.getPageNumber());
    // map.put(PAGE_SIZE, plist.getObjectsPerPage());
    // map.put(TOTAL_PAGE, plist.getPageCount());
    // map.put(TOTAL_RECORD, plist.getFullListSize());
    // map.put(PAGE_DATA, pageData);
    // return map;
    //
    // }

    /**
     * 获取错误信息 <br/>
     * <p>
     * Description: 通过异常名获取返回的错误信息 <br/>
     * <p>
     * Author: leiyu<br/>
     * <p>
     * Date: 2014-4-2-下午2:49:13<br/>
     * <p>
     *
     * @param exceptionName
     * @return 异常对应的错误信息
     */
    protected String getErrorMessage(String exceptionName) {
        try {
            return ((Properties) (propertiesFactory.getObject())).getProperty(exceptionName);
        } catch (IOException e) {
            // handleException(e);
            return "错误信息配置文件加载错误";
        }
    }

//	protected int getPage() {
//		String pageString = getRequest().getParameter("page");
//
//		if (StringUtils.isNotBlank(pageString)) {
//			return Integer.parseInt(pageString);
//		}
//
//		return PAGE;
//	}

//	protected int getPageSize() {
//		String pageSizeString = getRequest().getParameter("rows");
//		if (StringUtils.isBlank(pageSizeString)) {
//			pageSizeString = getRequest().getParameter("pageSize");
//		}
//		if (StringUtils.isNotBlank(pageSizeString)) {
//			return Integer.parseInt(pageSizeString);
//		}
//
//		return PAGE_SIZE;
//	}

    // @ModelAttribute
    // public void setReqAndResp(HttpServletRequest request, HttpServletResponse
    // response)
    // {
    // this.request = request;
    // this.response = response;
    // this.session = this.request.getSession();
    // this.setIpAddr(request);
    // }

    protected String getIpAddr() {
        return StringUtils.getIpAddr(getRequest());
    }

    /**
     * 允许跨域访问
     *
     * @param response
     */
    protected void setResponseToOpen(HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
    }


    public static final int CODE_SUCCESS = CodeConstant.CODE_SUCCESS;// 访问成功
    public static final int CODE_FAULT = CodeConstant.CODE_FAULT;// 访问成功


    public static final int CODE_EMPTY_REQUIRED = CodeConstant.CODE_EMPTY_REQUIRED;// 必填参数为空
    public static final int CODE_NEVER_FOUND = CodeConstant.CODE_NEVER_FOUND;// 未知的错误

    public static final int CODE_DOWNLOAD_ERROR = CodeConstant.CODE_DOWNLOAD_ERROR;// 未知的错误


    public static final int CODE_NOT_LOGIN = CodeConstant.CODE_NOT_LOGIN;// 没有登录状态


//	/**
//	 * @Fields OP_STATUS_SUCCESS :
//	 */
//	public static final int OP_STATUS_SUCCESS = 0;
//
//	/**
//	 * @Fields OP_STATUS_FAILD :
//	 */
//	public static final String OP_STATUS_FAILD = "1";
//
//	/**
//	 * @Fields OP_STATUS_FAILD :
//	 */
//	public static final String KEY_OP_STATUS = "code";
//	/**
//	 * @Fields OP_STATUS_FAILD :
//	 */
//	public static final String KEY_MSG_DESC = "msg";
//	/**
//	 * @Fields OP_STATUS_FAILD :
//	 */
//	public static final String KEY_DATA = "data";
//
//	/**
//	 * @Fields ERROR_KEY_MSG_TYPE : 返回值的key msgType
//	 */
//	public static final String ERROR_KEY_MSG_TYPE = "msgType";
//
//	/**
//	 * @Fields ERROR_KEY_MSG_DESC : 返回值的key msgDesc
//	 */
//	public static final String ERROR_KEY_MSG_DESC = "msgDesc";
//
//	/**
//	 * @Fields ERROR_KEY_OP_RESULT : 返回值的key opResult
//	 */
//	public static final String ERROR_KEY_OP_RESULT = "opResult";
//
//	/**
//	 * @Fields ERROR_VALUE_MSG_TYPE_INFO : 返回值的value 消息
//	 */
//	public static final String ERROR_VALUE_MSG_TYPE_INFO = "info";
//
//	/**
//	 * @Fields ERROR_VALUE_MSG_TYPE_WARN : 返回值的value 警告
//	 */
//	public static final String ERROR_VALUE_MSG_TYPE_WARN = "warning";
//
//	/**
//	 * @Fields ERROR_VALUE_MSG_TYPE_QUESTION : 返回值的value 疑问
//	 */
//	public static final String ERROR_VALUE_MSG_TYPE_QUESTION = "question";
//
//	/**
//	 * @Fields ERROR_VALUE_MSG_TYPE_ERROR : 返回值的value 错误
//	 */
//	public static final String ERROR_VALUE_MSG_TYPE_ERROR = "error";
//
//	/**
//	 * @Fields ERROR_VALUE_OP_RESULT_SUCCESS : 返回值操作结果 成功
//	 */
//	public static final String ERROR_VALUE_OP_RESULT_SUCCESS = "0";
//
//	/**
//	 * @Fields ERROR_VALUE_OP_RESULT_FAIL : 返回值操作结果 失败
//	 */
//	public static final String ERROR_VALUE_OP_RESULT_FAIL = "1";
//
//	/**
//	 * @Fields ZTREE_ROOT_VALUE : ztree 根节点的值
//	 */
//	public static final String ZTREE_ROOT_NODE_VALUE = "-1";
//
//	/**
//	 * @Fields ERROR_VALUE_OP_RESULT_SUCCESS_NAME : 获取操作结果 成功字段
//	 */
//	public static final String ERROR_VALUE_OP_RESULT_SUCCESS_NAME = "Success";

    // @InitBinder
    // public void initBinder(HttpServletRequest request,
    // ServletRequestDataBinder binder) throws Exception {
    // binder.registerCustomEditor(Date.class, new DateEditor());
    // }

    /**
     * 将对象的不为空的属性进行复制（将copied中属性的值复制到duplicate中）
     *
     * @param duplicate
     * @param copied
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public Object copyBeanNotEmptyFields(Object duplicate, Object copied)
            throws IllegalAccessException, InstantiationException {
        if (copied == null)
            return null;
        if (duplicate == null)
            duplicate = copied.getClass().newInstance();
        Field[] fields = copied.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            Object fieldValueObject = field.get(copied);
            if (fieldValueObject instanceof String) {
                String str = (String) fieldValueObject;
                if (StringUtils.isBlank(str)) {// 如果是String判断是否是空串，不为空串的才复制属性
                    continue;
                }
            }
            if (fieldValueObject != null) {// 判断是否为null，不为null就开始复制属性
                field.set(duplicate, fieldValueObject);// 复制
            }
        }
        return duplicate;
    }

    // @Resource
    // ISysConfigService sysConfigService;

    // /**
    // * 根据code获取返还至页面的文案信息
    // *
    // * @param code
    // * @return
    // */
    // public String returnMsg(String code) {
    // ISysConfigService sysConfigService = (ISysConfigService)
    // SpringContextUtil.getBean("sysConfigServiceImpl");
    // return sysConfigService.findByCode(code).getValue();
    //
    // }

    /**
     * 打印错误日志
     *
     * @param e
     * @throws IOException
     */
    protected void logErr(Exception e) {
        ByteArrayOutputStream out = null;
        try {
            out = new ByteArrayOutputStream();
            PrintStream s = new PrintStream(out);
            e.printStackTrace(s);
            String string = new String(out.toByteArray());
            if (StringUtils.isNotBlank(string)) {
                logger.error(string);
                logger.debug(string);
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        } finally {
            if (out != null)
                try {
                    out.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
        }

    }

    // 通用错误
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseEntity handleAllException(HttpServletRequest request, HttpServletResponse response,
                                             Exception ex) {
        // System.out.println("未知异常");
        logErr(ex);// 记录错误日志

        ResponseEntity entity = new ResponseEntity();
        entity.setCode(CODE_NEVER_FOUND);
        entity.setMsg("未知错误:" + ex.getClass().getSimpleName());
        return entity;
    }

    // 500 --业务逻辑错误
    @ExceptionHandler(BussinessException.class)
    @ResponseBody
    public ResponseEntity handleBussinessException(HttpServletRequest request, HttpServletResponse response,
                                                   BussinessException ex) {
        // System.out.println("业务错误");
//		logErr(ex);// 记录错误日志

        ResponseEntity entity = new ResponseEntity();
        entity.setCode(ex.getCode());
        entity.setMsg(ex.getMessage());
        return entity;
    }

    // 400 -- 权限错误
    @ExceptionHandler(HttpSendErrorException.class)
    @ResponseBody
    public void handleAuthorityExceptionException(HttpServletRequest request, HttpServletResponse response,
                                                  HttpSendErrorException ex) throws Exception {
        response.sendError(ex.getCode(), ex.getMessage());

    }

    /**
     * 抛出空参数异常
     *
     * @param msg
     */
    protected void throwCodeEmptyException(String msg) {
        if (StringUtils.isBlank(msg)) {
            msg = "必填参数为空";
        }
        BussinessException bet = new BussinessException(msg);
        bet.setCode(CODE_EMPTY_REQUIRED);
        throw bet;
    }

    /**
     * 抛出权限相关的异常
     *
     * @param code
     * @param msg
     */
    protected void throwHttpSendErrorExceptionException(int code, String msg) {
        if (StringUtils.isBlank(msg)) {
            msg = "没有登录状态";
        }
        HttpSendErrorException ex = new HttpSendErrorException(msg);
        ex.setCode(code);
        throw ex;
    }


    protected void selectByPage(Page page, Object example, IBaseService service) throws Exception {
        if(page == null){
            page = new Page();
        }
        PageHelper.startPage(page.getPage(), page.getRows(), true);
        List list = service.selectByExample(example);
        page.setList(list);
        // 分页详情
        PageInfo pageInfo = new PageInfo(list);
        page.setTotalCount((int)pageInfo.getTotal());

    }
}
